package com.isd.facturacion.rn;

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

import com.isd.facturacion.dao.MovimientoFacturacionDAO;
import com.isd.facturacion.modelo.ItemComponenteTienda;
import com.isd.facturacion.modelo.ItemMovimientoTiendaPK;
import com.isd.facturacion.modelo.ItemProductoFacturacion;
import com.isd.facturacion.modelo.ItemProductoTienda;
import com.isd.facturacion.modelo.MovimientoFacturacion;
import com.isd.facturacion.modelo.MovimientoFacturacionPK;
import com.isd.facturacion.modelo.MovimientoTienda;
import com.isd.facturacion.modelo.MovimientoTiendaPK;
import com.isd.facturacion.vista.ComprobantesPendientes;
import com.isd.facturacion.vista.PedidoProducto;
import com.isd.facturacion.vista.ProductoPendiente;
import com.isd.global.dao.ComprobanteDAO;
import com.isd.global.excepciones.ExcepcionGeneralSistema;
import com.isd.global.excepciones.PreexistingEntityException;
import com.isd.global.excepciones.RollbackFailureException;
import com.isd.global.modelo.Moneda;
import com.isd.global.modelo.Sucursal;
import com.isd.global.rn.MonedaRN;
import com.isd.global.rn.SucursalRN;
import com.isd.global.util.JsfUtil;
import com.isd.inventario.modelo.Producto;
import com.isd.inventario.modelo.ST_ItemComposicionFormula;
import com.isd.inventario.rn.ListaPrecioRN;
import com.isd.inventario.vista.ItemCatalogo;
import com.isd.venta.modelo.Cliente;
import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.ejb.EJB;
import javax.ejb.Stateless;

/**
 *
 * @author Claudio
 */
@Stateless
public class MovimientoFacturacionRN {

    @EJB private SucursalRN SucursalRN;
    @EJB private MonedaRN monedaRN;
    @EJB private MovimientoFacturacionDAO movimientoFacturacionDAO;
    @EJB private ComprobanteDAO comprobanteDAO;
    @EJB private ListaPrecioRN listaPrecioRN;
    
//synchronized
    public  void guardar(MovimientoTienda m) throws Exception {
        
        if(movimientoFacturacionDAO.getMovimientoTiendaById(m.getId())==null)
            movimientoFacturacionDAO.crear(m);
        else
            movimientoFacturacionDAO.editar(m);
    }

    public void calcularImportesDocumento(MovimientoTienda carrito) {

        //Logger.getLogger(getClass().getName()).log(Level.SEVERE, "calcularImportesDocumento", "Falta implementación");                                    
    }

    public List<MovimientoTienda> getCarritoSinConfirmarCliente(Cliente c) {
        
        Map<String,String> filtro = new HashMap<String,String>();
        filtro.put("cliente.nrocta =","'" + c.getNrocta() + "' ");
        filtro.put("debaja = ", "'N'");
        filtro.put("estaut = ", "'0'");
        filtro.put("circom = ", "'0110'");
        filtro.put("cirapl = ", "'0110'");

        return movimientoFacturacionDAO.getMovimientosTienda(filtro);
    }

    public List<MovimientoTienda> getCarritoSinConfirmarVendedor(Cliente c) {

        Map<String,String> filtro = new HashMap<String,String>();
        filtro.put("cliente.nrocta =","'" + c.getNrocta() + "' ");
        filtro.put("debaja = ", "'N'");
        filtro.put("estaut = ", "'0'");
        filtro.put("circom = ", "'0120'");
        filtro.put("cirapl = ", "'0120'");

        return movimientoFacturacionDAO.getMovimientosTienda(filtro);
    }

    public List<ComprobantesPendientes> getCarritosEnProcesoCliente(Cliente c){

        Map<String,String> filtro = new HashMap<String,String>();
        filtro.put("nrocta", c.getNrocta());
        filtro.put("circom", "0110");
        filtro.put("estaut", "1");
        
        return movimientoFacturacionDAO.getComprobantesPendientes(filtro);
    }

    public List<ComprobantesPendientes> getCarritosEnProcesoVendedor(Cliente c){

        Map<String,String> filtro = new HashMap<String,String>();
        filtro.put("nrocta", c.getNrocta());
        filtro.put("circom", "0120");
        filtro.put("estaut", "1");

        return movimientoFacturacionDAO.getComprobantesPendientes(filtro);
    }

    public List<ComprobantesPendientes> getPedidosPendientes(Cliente c){

        Map<String,String> filtro = new HashMap<String,String>();
        filtro.put("nrocta", c.getNrocta());
        filtro.put("circom", "0200");
        
        return movimientoFacturacionDAO.getComprobantesPendientes(filtro);
    }
    
    public MovimientoTienda nuevoMovimiento(Cliente cliente,String modfor,String codfor, String circuito) throws ExcepcionGeneralSistema {
        try {

            if(cliente==null){

                throw new ExcepcionGeneralSistema("El cliente no puede ser nulo");
            }

            Moneda coeficiente = monedaRN.getMoneda("ARS");
            BigDecimal cotizacionDia = monedaRN.getCotizacionDia("USD");
            Sucursal sucursal = SucursalRN.getSucursal("0001");

            MovimientoTienda m = new MovimientoTienda();
            MovimientoTiendaPK mPK = new MovimientoTiendaPK();

            mPK.setModfor(modfor);
            mPK.setCodfor(codfor);
            mPK.setNrofor(comprobanteDAO.getNumeroComprobante(modfor, codfor));
            m.setId(mPK);

            m.setSucursal(sucursal);
            m.setFchmov(JsfUtil.getFecha());

            m.setModgen(mPK.getModfor());
            m.setCodgen(mPK.getCodfor());
            m.setNrogen(mPK.getNrofor());

            m.setCircom(circuito);
            m.setCirapl(circuito);
            m.setCirgen(circuito);
            m.setEstaut(Short.valueOf("0"));
            m.setCliente(cliente);

            if (cliente.getSitio().getCodigo().equals("000002") && !cliente.getJurisdiccion().getJurisd().equals("924")) {
                m.setFlcinp('S');
                m.setFlcpor(cliente.getFlcpor());
            } else {
                m.setFlcinp('N');
                m.setFlcpor(BigDecimal.ZERO);
            }
            
            //Porcentajes de percepcioens
            m.setPib902(cliente.getPib902());
            m.setPib903(cliente.getPib903());
            m.setPib909(cliente.getPib909());
            m.setPib914(cliente.getPib914());
            m.setPib918(cliente.getPib918());
            m.setPib921(cliente.getPib921());
            m.setPib924(cliente.getPib924());

            m.setNrosub(cliente.getNrocta());
            m.setVendedor(cliente.getVendedor());
            m.setCondicionDePago(cliente.getCondicionDePago());
            m.setCondicionDeIva(cliente.getCondicionDeIva());

            if(cliente.getValorUltimoScore()!=null){
                m.setValorUltimoScore(cliente.getValorUltimoScore());
            }

            if(cliente.getFechaUltimoScore()!=null){
                m.setFechaUltimoScore(cliente.getFechaUltimoScore());
            }

            m.setCoeficienteDeuda(coeficiente);
            m.setCoeficienteEmision(coeficiente);
            m.setCoeficienteRegistracion(coeficiente);
            m.setCamsec(cotizacionDia);

            //Datos de entrega
            m.setJurisdiccion(cliente.getJurisdiccion());
            m.setPais(cliente.getPais());
            m.setCodigoPostalEntrega(cliente.getCodigoPostal());
            m.setDirent(cliente.getDirent());
                        
            m.setSitio(cliente.getSitio());
            m.setDeposito(cliente.getSitio().getDeposito());
            m.setSector(cliente.getSitio().getSector());
            m.setListaDePrecio(cliente.getListaDePrecio());
            m.setFeclis(JsfUtil.getFecha());
            m.setCongel('S');
            
            m.setItemsProducto(new ArrayList<ItemProductoTienda>());

            return m;
            
        } catch (ExcepcionGeneralSistema e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "nuevoMovimiento", e);                                    
            return null;
        } catch (NumberFormatException e) {
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "nuevoMovimiento", e);
            return null;
        }
    }
    
    public ItemProductoTienda nuevoItemProducto(MovimientoTienda m){
        
        int maxNroItem = calcularMaximoNroItem(m);
              
        //m.getItemsProducto().size()       
        
        ItemProductoTienda nItem = new ItemProductoTienda();
        ItemMovimientoTiendaPK iPK = new ItemMovimientoTiendaPK(
                m.getId().getModfor(),
                m.getId().getCodfor(),
                m.getId().getNrofor(),
                maxNroItem,
                "1",
                m.getId().getModfor(),
                m.getId().getCodfor(),
                m.getId().getNrofor(),
                maxNroItem,
                "1");

        nItem.setItemMovimientoVentaPK(iPK);
        nItem.setMovimiento(m);
        nItem.setMovimientoAplicacion(m);        

        return nItem;
    }
    
    public ItemComponenteTienda nuevoItemComponente(MovimientoTienda m, 
            ItemProductoTienda ip,
            ST_ItemComposicionFormula icf){

        ItemComponenteTienda nItem = new ItemComponenteTienda();
        ItemMovimientoTiendaPK iPK = new ItemMovimientoTiendaPK(
                ip.getItemMovimientoVentaPK().getModfor(),
                ip.getItemMovimientoVentaPK().getCodfor(),
                ip.getItemMovimientoVentaPK().getNrofor(),
                ip.getItemMovimientoVentaPK().getNroitm(),
                "1" + icf.getNroitm(),
                ip.getItemMovimientoVentaPK().getModfor(),
                ip.getItemMovimientoVentaPK().getCodfor(),
                ip.getItemMovimientoVentaPK().getNrofor(),
                ip.getItemMovimientoVentaPK().getItmapl(),
                "1" + icf.getNroitm());

        nItem.setOalias("FCRMVK");
        nItem.setItemMovimientoVentaPK(iPK);
        nItem.setMovimiento(m);
        nItem.setMovimientoAplicacion(m);        

        return nItem;
    }
    
    public void agregarProducto(MovimientoTienda m, Producto p,BigDecimal cantidad, BigDecimal pcioBase){

        ItemProductoTienda item = new ItemProductoTienda();
        ItemMovimientoTiendaPK iPK = new ItemMovimientoTiendaPK(
                m.getId().getModfor(),
                m.getId().getCodfor(),
                m.getId().getNrofor(),
                m.getItemsProducto().size(),
                "1",
                m.getId().getModfor(),
                m.getId().getCodfor(),
                m.getId().getNrofor(),
                m.getItemsProducto().size(),
                "1");
        try {

            item.setItemMovimientoVentaPK(iPK);
            item.setCantid(cantidad);
            item.setProducto(p);

            item.setPrecio(pcioBase);
            item.setPrenac(pcioBase);
            item.setPresec(pcioBase.divide(monedaRN.getCotizacionDia("USD"), 4 ,BigDecimal.ROUND_FLOOR));

            item.setPctbf1(BigDecimal.ZERO);
            item.setPctbf2(BigDecimal.ZERO);
            item.setPctbfn(BigDecimal.ZERO);

            //Precio final con bonificacion incluida
            BigDecimal precioFinal = pcioBase.add(pcioBase.multiply(item.getPctbfn()).divide(new BigDecimal(100)));

            item.setTotlin(precioFinal);

            item.setMonedaListaPrecio(m.getCoeficienteDeuda());
            item.setDeposito(m.getDeposito());
            item.setSector(m.getSector());
            item.setSucursal(m.getSucursal());
            item.setCliente(m.getCliente());
            item.setFchent(new Date());
            item.setFchhas(new Date());
            item.setUnimed(p.getUnidadMedida().getUnidad());
            item.setUnifac(p.getUnidadMedida().getUnidad());

            item.setMovimiento(m);

            m.getItemsProducto().add(item);
            calcularImportesDocumento(m);

        } catch (Exception e){
            m.getItemsProducto().remove(item);
            Logger.getLogger(getClass().getName()).log(Level.SEVERE, "agregarProducto", e);           
        }
    }   
    
    public void generoItemsComponente(MovimientoTienda movimiento) {
        
        if(movimiento.getItemsComponente()==null){
            movimiento.setItemsComponente(new ArrayList<ItemComponenteTienda>());
        }else{
            movimiento.getItemsComponente().clear();
        }        
        
        for(ItemProductoTienda i: movimiento.getItemsProducto()){
            
            if(i.getProducto().getComposicionFormulaVenta()==null) continue;
            
            for(ST_ItemComposicionFormula icf : i.getProducto().getComposicionFormulaVenta().getItemComposicion()){            
            
                ItemComponenteTienda ic = nuevoItemComponente(movimiento, i, icf);
                
                ic.setCantid(icf.getCntnom().multiply(i.getCantid()));
                ic.setCantst(ic.getCantid());
                ic.setCntori(ic.getCantid());
                ic.setProducto(icf.getProductoComponente());
                
                BigDecimal cotizacion = monedaRN.getCotizacionDia((icf.getProductoComponente().getMonedaUltimaCompra()==null?"ARS":icf.getProductoComponente().getMonedaUltimaCompra()));
                //Precio de lista
                BigDecimal precio = icf.getProductoComponente().getPrecioUltimaCompra().multiply(cotizacion);      
            
                ic.setPrecio(precio);
                ic.setPrenac(precio);
                ic.setPresec(precio.divide(monedaRN.getCotizacionDia("USD"), 4 ,BigDecimal.ROUND_FLOOR));

                ic.setPctbf1(BigDecimal.ZERO);
                ic.setPctbf2(BigDecimal.ZERO);
                ic.setPctbfn(BigDecimal.ZERO);           

                ic.setTotlin(ic.getCantid().multiply(ic.getPrecio()));
                
                //ic.setMonedaListaPrecio(movimiento.getCoeficienteDeuda());
                ic.setDeposito(movimiento.getDeposito());
                ic.setSector(movimiento.getSector());
                ic.setSucursal(movimiento.getSucursal());
                //ic.setCliente(movimiento.getCliente());
                ic.setFchent(new Date());
                ic.setFchhas(new Date());
                ic.setUnimed(icf.getUnidadMedidaItem().getUnidad());
                ic.setUnifac(icf.getUnidadMedidaItem().getUnidad());
                
                ic.setTipcpt(null);
                ic.setModcpt(null);
                ic.setCodcpt(null);   
                ic.setCuenta(null);
                ic.setCambio(null);
                
                movimiento.getItemsComponente().add(ic);
            }   
        }
    }

    public void recalcularValores(MovimientoTienda m, boolean actualizaPrecios){

        if(m.getItemsProducto()==null) return;
        if(m.getItemsProducto().isEmpty()) return;

        for(ItemProductoTienda i: m.getItemsProducto()){

            if(actualizaPrecios){

                ItemCatalogo ic = listaPrecioRN.getItemCatalogoByProducto(i.getProducto(), m.getCliente().getNrocta());
                BigDecimal cotizacion = monedaRN.getCotizacionDia(ic.getMoneda());
                BigDecimal precio = ic.getPrecioLista().multiply(cotizacion);
                i.setPrecio(precio);
                i.setPresec(precio.divide(monedaRN.getCotizacionDia("USD"), 4 ,BigDecimal.ROUND_FLOOR));
                i.setPctbf1(ic.getBonificacion());                
            }           

            //Bonificacion final del precio
            BigDecimal bonificacionFinal = i.getPctbf1().add(i.getPctbf2());
            
            //Precio final con bonificacion incluida
            BigDecimal precioFinal = i.getPrecio().add(i.getPrecio().multiply(i.getPctbfn()).divide(new BigDecimal(100)));
            
            //Total linea
            BigDecimal totalLinea = i.getCantid().multiply(precioFinal);

            i.setPctbfn(bonificacionFinal);
            i.setTotlin(totalLinea);
            
        }

    }

    public List<String> generarMensajeCorreoElectronico(MovimientoTienda carrito) {

        SimpleDateFormat formateadorFecha = new SimpleDateFormat("dd/MM/yyyy");

        List<String> contenido = new ArrayList<String>();

        contenido.add("<b>Estimado Cliente:</b>");
        contenido.add("Gracias por su compra. Su pedido será gestionado en breve");
        contenido.add("Detalle del pedido:");
        
        contenido.add("<hr/>");
        contenido.add("Fecha comprobante: " + formateadorFecha.format(carrito.getFchmov()));
        contenido.add("Número comprobante: " + carrito.getId().getNrofor());
        contenido.add("Condición: " + carrito.getCondicionDePago().getDescrp());
        contenido.add("Observaciones: " + (carrito.getTextos()==null?"":carrito.getTextos()));
        contenido.add("<hr/>");
        contenido.add("Detalle de productos"+ "\n");

        String sItems ="";

        if(!carrito.getItemsProducto().isEmpty()){
            sItems += "<table style=\"font-family: Arial, Helvetica, sans-serif; width: 700px; border: 0px solid #eeeeee;\" border=\"0\" cellspacing=\"2\" cellpadding=\"0\" align=\"center\">";
            sItems += "<tr><td><b>Cant.</b></td>"
                    + "<td align=\"center\" ><b>Descripción</b></td> "
                    + "<td align=\"right\" width=\"30\"><b>Pcio. Unit.</b></td>"
                    + "<td align=\"right\" width=\"30\" ><b>Subtotal c/IVA</b></td></tr>";

            for(ItemProductoTienda i: carrito.getItemsProducto()){

                sItems += "<tr><td align=\"right\" width=\"15\" >"+i.getCantid().toBigInteger()+"</td>";
                sItems += "<td style=\"margin-left: 10px;\">"+i.getProducto().getDescrp().trim()+"</td>";
                sItems += "<td align=\"right\" width=\"50\" >"+i.getPrecioFinalConIVA().setScale(2,2)+"</td>";
                sItems += "<td align=\"right\" width=\"50\" >"+i.getTotalLineaConIVA().setScale(2,2)+"</td></tr>";
            }

            sItems += "<tr><td align=\"right\" colspan=\"2\"><b>Total c/IVA:</b></td><td align=\"right\"><b>$"+carrito.getSubTotalConIVA().setScale(2,2)+"</b></td></tr></table>";
        }        

        contenido.add(sItems);
        contenido.add("<hr>");       

        return contenido;
    }    

    public Object generarPDF(MovimientoTienda carrito) {
        return null;
    }
    
    public MovimientoTienda getMovimientoTienda(String modapl, String codapl, int nroapl, boolean obtienePendientes) {

        MovimientoTiendaPK idPK;idPK = new MovimientoTiendaPK(modapl, codapl, nroapl);
        MovimientoTienda m = movimientoFacturacionDAO.getMovimientoTiendaById(idPK);        
        return m;
    }

    public MovimientoFacturacion getMovimientoFacturacion(String modapl, String codapl, int nroapl, boolean obtienePendientes) {

        MovimientoFacturacionPK idPK;idPK = new MovimientoFacturacionPK(modapl, codapl, nroapl);
        MovimientoFacturacion m = movimientoFacturacionDAO.getMovimientoFacturacionById(idPK);
        if(obtienePendientes) obtenerPendientesPorMovimiento(m);
        return m;

    }

    public void obtenerPendientesPorMovimiento(MovimientoFacturacion m){
        for(ItemProductoFacturacion i: m.getItemsProducto()){

            i.setPendiente(movimientoFacturacionDAO.getPendienteItem(i));
        }
    }

    public void eliminarItem(ItemProductoTienda remove) throws PreexistingEntityException, RollbackFailureException, Exception {

        movimientoFacturacionDAO.eliminar(ItemProductoTienda.class, remove.getItemMovimientoVentaPK());

    }

    public List<MovimientoFacturacion> getPedidosFacturados(Cliente cliente) {

        return movimientoFacturacionDAO.getPedidosFacturados(cliente);
    }

    /**
     * 
     * @param cliente
     * @return Devuelve una lista de objetos ProductoPendiente, que representan
     * los productos pendiente por un cliente específico
     */
    public List<ProductoPendiente> getProductosPendientes(Cliente cliente) {

        return movimientoFacturacionDAO.getProductosPendientes(cliente);
    }

    /**
     *
     * @param tipo : Codigo tipo 
     * @param codigo: Codigo producto
     * @param nrocta: Numero cuenta cliente
     * @return Devuelve un objeto de ProductoPendiente informando la cantidad de pendiente para el produto consultado
     */
    public ProductoPendiente getPendientePorProducto(String tipo,String codigo, String nrocta) {

        return movimientoFacturacionDAO.getPendientePorProducto(tipo,codigo,nrocta);
    }

        /**
     *
     * @param nrocta : Nro de cuenta
     * @param tippro : Tipo de producto
     * @param artcod : Codigo de produto
     * @return Devuelve la lista de pedidos en los cuales se encuentra pendietne el producto consultado
     */
    public List<PedidoProducto> getPendientePorPedidoProducto(String nrocta, String tippro, String artcod){

        return movimientoFacturacionDAO.getPendientePorPedidoProducto(nrocta, tippro, artcod);

    } 

    private int calcularMaximoNroItem(MovimientoTienda m) {
        
        int maxNroItem = 0;
        
        if(m.getItemsProducto()==null){            
            return 0;
        }
        
        for(ItemProductoTienda ipt: m.getItemsProducto()){
            
            if(ipt.getItemMovimientoVentaPK().getNroitm()>= maxNroItem){
                
                maxNroItem = ipt.getItemMovimientoVentaPK().getNroitm();
            }            
        }        
        return ++maxNroItem;
    }
}

